<?php

class Catalogue_Model_Category_Storage_Table extends Workset_Model_Object_Storage_Table_Abstract {

	protected $_objectClass 	= 'Catalogue_Model_Category';

    protected $_iteratorClass 	= 'Catalogue_Model_Object_Iterator';

	protected $_tableClass 		= 'Catalogue_Table_Category';

	protected $_attrObjectClass = 'Catalogue_Model_Attribute';

	protected $_attrTableClass 	= 'Catalogue_Table_Attribute';

	protected $_categoryAttrTableClass = 'Catalogue_Table_Category_Attribute';

    protected $_linkedObjectTableClass = 'Catalogue_Table_Object_Category';

	function setAttrObjectClass($class) {
		$this->_attrObjectClass = $class;
	}

	function setAttrTableClass($class) {
		$this->_attrTableClass = $class;
	}

	function setCategory2AttrTableClass($class) {
		$this->_categoryAttrTableClass = $class;
	}

	function setObject2ObjectTableClass($class) {
		$this->_linkedObjectTableClass = $class;
	}

	function setOptions(array $options) {
		parent::setOptions($options);

		foreach ($this->_options as $key => $option) {
			switch ($key) {
				case 'category2AttrTableClass':
					$this->setCategory2AttrTableClass($option);
					unset($this->_options[$key]);
				break;

				case 'object2ObjectTableClass':
					$this->setObject2ObjectTableClass($option);
					unset($this->_options[$key]);
				break;

				case 'attrObjectClass':
					$this->setAttrObjectClass($option);
					unset($this->_options[$key]);
				break;

				case 'attrTableClass':
					$this->setAttrTableClass($option);
					unset($this->_options[$key]);
				break;
			}
		}
	}

    /*function addAttribute(Catalogue_Model_Category $category,
                          Catalogue_Model_Attribute $attr)
    {

        $row = $category->getData();
        if ($row instanceof Workset_Db_Table_Row) {
            return $row->addDependentRow($this->_categoryAttrTableClass, array(
               'attr_id' => $attr->getId()
            ));
        }
    }*/

    /*function deleteAttribute(Catalogue_Model_Category $category,
                             Catalogue_Model_Attribute $attr)
    {
        $row = $category->getData();
        if ($row instanceof Workset_Db_Table_Row) {
            $intersectRow = $row->findDependentRow($this->_categoryAttrTableClass, 'category', array(
                "attr_id = {$attr->getId()}"
            ));
            return $intersectRow->delete();
        }
    }*/

    function getAttributes( Catalogue_Model_Category $category,
                            $where = null, $order = null, $limit = null, $offset = null, $checkParents = false)
    {
        if (true == $checkParents) {
            return $this->_getAttributes($category, $where, $order, $limit, $offset);
        } else {
            return $this->_getOnlySelfAttributes($category, $where, $order, $limit, $offset);
        }
    }

    protected function _getOnlySelfAttributes(Catalogue_Model_Category $category,
                            $where = null, $order = null, $limit = null, $offset = null)
    {
        $matchTable = $this->_getTable($this->_attrTableClass);
        $intersectTable = $this->_getTable($this->_categoryAttrTableClass);

	    $select = $matchTable->prepareSelect($where, $order, $limit, $offset);

        $select->from(
                    array('m' => $matchTable->info(Zend_Db_Table_Abstract::NAME))
                )
                ->join(
                    array('i' => $intersectTable->info(Zend_Db_Table_Abstract::NAME)),
                     "i.attr_id = m.id",
                    array()
                );

        $where = array();

        if ($category->hasParent()) {
            $parents = $category->getParents()->toArray('id');
            array_push($parents, $category->getId());

            $where["i.category_id in(?)"] = $parents;

        } else {
            $where["i.category_id = ?"] = $category->getId();
        }

        $select->where(
            key($where), current($where)
        );

        $rowset = $matchTable->fetchAll($select);

        return $this->getIterator($rowset, array(
            'filter' => $select,
            'storage' => null,
			'objectClass' => $this->_attrObjectClass
        ));
    }

    protected function _getAttributes(Catalogue_Model_Category $category,
                            $where = null, $order = null, $limit = null, $offset = null)
    {
        $row = $category->getData();
        if ($row instanceof Workset_Db_Table_Row) {
        	$table = $row->getTable();

			$select = $table->prepareSelect($where, $order, $limit, $offset, true);

            $rowset = $row->findManyToManyRowset($this->_attrTableClass, $this->_categoryAttrTableClass, 'category', null, $select);

            return $this->getIterator($rowset, array(
				'storage' => null,
				'objectClass' => $this->_attrObjectClass,
                'filter' => $select,
			));
        }
    }

    function linkToObject(Workset_Model_Object_Interface $object,
						  Workset_Model_Object_Interface $refObject,
						  $data = null	)
	{
		$row = $object->getData();
        if ($row instanceof Workset_Db_Table_Row) {

			if (is_array($data)) {
				$data = array_merge($data, array(
					'object_id' => $refObject->getId(),
				));
			} else {
				$data = array(
					'object_id' => $refObject->getId(),
				);
			}

            return $row->addDependentRow($this->_linkedObjectTableClass, $data);
        }
    }

    function unlinkObject(Workset_Model_Object_Interface $object,
						  Workset_Model_Object_Interface $refObject)
	{
        $row = $object->getData();
        if ($row instanceof Workset_Db_Table_Row) {
            $subrow = $row->findDependentRow($this->_linkedObjectTableClass, 'category', array(
                'object_id = ?' => $refObject->getId(),
            ));
            if ($subrow) {
                return $subrow->delete();
            }
        }
    }

    function setAttributePriority(Workset_Model_Object_Interface $object,
                                 Workset_Model_Object_Interface $attr,
                                 $priority)
    {
        $table = $this->_getTable($this->_categoryAttrTableClass);

        $priority = (int)$priority;

        $result = $table->update(
            array(
                'priority' => $priority
            ),
            array(
                'category_id = ?' => $object->getId(),
                'attr_id = ?' => $attr->getId()
            )
        );

		$where = array(
			'attr_id != ?' => $attr->getId(),
			'priority >= ?' => $priority
		);

		$this->updateAttributePriority($object, $where);

        return $result;
    }

	function getMaxAttributePriority(Workset_Model_Object_Interface $object) {

		$table = $this->_getTable($this->_categoryAttrTableClass);
		$select = $table->getAdapter()->select();
		$name = $table->info(Zend_Db_Table_Abstract::NAME);

		$select	->from($name, array(new Zend_Db_Expr('MAX(priority) as priority')))
        		->where('category_id = ?', $object->getId());

		$result = $table->getAdapter()->fetchOne($select);

		if (false !== $result) {
			return (int)$result;
		} else {
			return 1;
		}
	}

	function getAttributePriority(Workset_Model_Object_Interface $object,
								 Workset_Model_Object_Interface $attr)
	{
		$table = $this->_getTable($this->_categoryAttrTableClass);
		$select = $table->getAdapter()->select();
		$name = $table->info(Zend_Db_Table_Abstract::NAME);

		$select	->from($name, array('priority'))
        		->where('category_id = ?', $object->getId())
				->where('attr_id = ?', $attr->getId());

		$result = $table->getAdapter()->fetchOne($select);

		if (false !== $result) {
			return (int)$result;
		} else {
			return 1;
		}
	}

	function updateAttributePriority(Workset_Model_Object_Interface $object, $where = null, $value = null) {
		if (empty($where)) {
			$where = array('category_id = ?' => $object->getId());
		} else {
			$where = (array)$where;
			$where['category_id = ?'] = $object->getId();
		}

		$table = $this->_getTable($this->_categoryAttrTableClass);

		if (empty($value)) {
			$value = 1;
		} else {
			$value = (int)$value;
		}

		return $table->update(
			array(
				'priority' => new Zend_Db_Expr("priority + $value")
			),
			$where
		);
	}

}

?>